# -*- coding: latin-1 -*-
"""Environment configuration for {{ project_name }} projects."""

__author__ = '{{ authors }}'
__version__	= '0.1'


__all__ = ['{{ module }}']

#classes for export
import sys, os, os.path, glob, re, getpass, platform, base64
from {{ module.lower() }}.exceptions import *
from {{ module.lower() }}.validations import *
from {{ module.lower() }}.utilities import new_session
from {{ module.lower() }}.shell import shell
import {{ module.lower() }}.crypto as crypto
from stat import *

#class for project information
class {{ module }}(object):

	root_user = 'root'

	#this searches the directory argument for the {{ project_name }} project root

	def find_project_root(dir_to_check):

		path_to_check = dir_to_check
		
		found = False
		while True:
			if(os.path.exists(path_to_check+"/config") \
							and os.path.exists(path_to_check+"/src") \
							and os.path.exists(path_to_check+"/libs/python/{{ module.lower() }}") \
							and os.path.exists(path_to_check+"/examples") \
							):
							found=True
							break
			else:
				path_to_check = os.path.dirname(path_to_check)
			
			if path_to_check == os.path.split(path_to_check)[0]:
				break
		
		if found:
			return path_to_check
		else:
			return None

	
	#search for {{ project_name }} dir
	dirs = sys.path
	dirs.insert(0, os.getcwd())

	found_root = False
	project_root = None
	for d in dirs:
		project_root = find_project_root(d)

		#find it?
		if (project_root != None):
			found_root = True
			break

	if(sys.path[0] == '' and found_root == False):
		print " Interactive shell detected..."
		project_root = raw_input("\n Please input the root of your {{ project_name }} project: ")
		project_root = re.sub(r'\\','\\\\\\\\',project_root) #yes this is ridiculous
	
	#find project root?
	#if not raise exception
	if(found_root == False):
		raise ProjectRootNotFound(sys.path[0])

	#adds the /src/model directory to the PYTHONPATH env var
	#this adds support for all the models
	models_dir = project_root + '/src/models/'
	if((models_dir in sys.path) == False):
		sys.path.append(models_dir)

	from config_model import Option, Config, Driver

	#adds the /libs/python/ directory to the PYTHONPATH env var
	#this adds support for all the models
	depend_dir = project_root + '/libs/python/'
	if((depend_dir in sys.path) == False):
		sys.path.append(depend_dir)
	
	#setting up configuration
	config_path = os.path.normpath(project_root+"/config/config.db")
	if not os.path.exists(config_path):
		raise Exception, "Project configuration has not been setup. Please run 'spyrim-setup-project'."
		# cwd = os.getcwd()
		# shell("python setup_config_db.py")
		# os.chdir(cwd)
	
	db_path = os.path.relpath(config_path, os.getcwd())
	config_session = new_session("sqlite:///"+db_path)

	# tables = config_session.execute("select * from sqlite_master where type='table' order by name;").fetchall()
	# print tables

	# getting current profile name
	_key = config_session.query(Option).filter(Option.key == 'current_profile').limit(1).all()
	if not _key:
		profile_name = None
	else:
		profile_name = _key[0].value
		
	current = None
	if not profile_name:
		raise Exception, "No profile has been selected! Please use the task manager to set one: 'make config:set_current_profile'."
	else:
		profile = config_session.query(Config).filter(Config.name == profile_name).all()
		
		if profile:
			current = profile[0]
		else:
			raise Exception, "No profile with that name! Please create one or reset the current profile with 'make config:new' or 'make config:set_current_profile'."

	#gets current analysis profile
	# current = get_current_profile()
	current_host = current.analysis_profile.host
	profile_name = current.name

	#data directories
	data_dir = current.analysis_profile.data_directory
	results_dir = current.analysis_profile.results_directory
	html_dir = current.analysis_profile.html_directory

	#gets the list of avaliable drivers
	drivers = {}
	for drv in config_session.query(Driver).all():
		drivers[drv.alias] = drv.driver

	#get db login info
	logins={}
	with open(project_root+'/config/login_info.csv','r') as f:
		for l in f:
			if l.startswith('#') or len(l.strip()) < 1:
				continue

			row=l.rstrip('\n').rstrip('\r').split(',')
			if(len(row) != 3):
				break

			alias = {}
			alias['host']= current_host
			alias['username']=row[0]
			alias['password']=row[1]
			alias['driver']=row[2]
			alias['decrypted'] = None

			logins[row[0]] = alias

	@classmethod
	def get_os(self):
		return platform.system()

	@classmethod
	def get_root_user(self):
		"""returns the root user for the database"""
		return self.root_user

	@classmethod
	def get_drivers(self):
		"""returns a *dict* of all the database drivers"""
		return self.drivers

	@classmethod
	def get_driver(self, user):
		"""returns the database driver for the current user"""
		{{ module }}.validate_user(user)
		return {{ module }}.get_drivers()[{{ module }}.login_info()[user]['driver']]
	
	@classmethod
	def get_project_root(self):
		"""returns the directory of the current analysis profile"""
		return self.project_root

	@classmethod
	def get_data_directory(self):
		"""returns the data directory for the current analysis profile"""
		return data_dir

	@classmethod
	def get_results_directory(self):
		"""Returns the *results* directory for the current analysis profile."""
		return results_dir

	@classmethod
	def get_html_directory(self):
		"""Returns the *html* directory for the current analysis profile."""
		return html_dir

	@classmethod
	def get_current_profile(self):
		"""gets the current analysis profile"""
		return self.profile_name

	@classmethod
	def get_current_host(self):
		"""returns the current database location / host"""
		return self.current_host

	@classmethod
	def get_config_session(self):
		"""This function returns a db sesison for the config db"""
		return self.config_session

	@classmethod
	def get_option(self, __key):
		"""returns a value for the given key"""
		from {{ module.lower() }} import {{ module }}
		from config_model import Option
		
		session = {{ module }}.get_config_session()
		# _key = session.query(self.__class__()).filter(self.__class__().key == key).all()
		_key = session.query(Option).filter(Option.key == __key).limit(1).all()
		if not _key:
			# session.close()
			return None
		else:
			# session.close()
			return _key[0].value

	@classmethod
	def set_option(self, __key, __value):
		"""returns a value for the given key"""
		from {{ module.lower() }} import {{ module }}
		from config_model import Option
		
		session = {{ module }}.get_config_session()
		_key = session.query(Option).filter(Option.key == __key).limit(1).all()
		if not _key:
			session.add(Option(str(__key), str(__value)))
			session.commit()
		else:
			_key[0].value = __value
			session.commit()

		return True

	@classmethod
	def del_option(self, __key):
		"""deletes a given option"""
		from {{ module.lower() }} import {{ module }}
		from config_model import Option
		
		session = {{ module }}.get_config_session()
		_key = session.query(Option).filter(Option.key == __key).limit(1).all()
		if not _key:
			return False
		else:
			# _key[0].value = __value
			session.delete(_key[0])
			session.commit()

		return True

	@classmethod
	def get_current_profile(self):
		"""returns the current data profile"""
		return self.current
		
	@classmethod
	def set_current_profile(self, profile_name):
		"""sets and returns the current data profile"""
		from config_model import Config
		
		self.set_option("current_profile", profile_name)
		profile = None
		
		if not profile_name:
			raise Exception, "Profile name must be given! Please use the task manager to set one: 'make config:set_current_profile'."
		else:
			session = self.get_config_session()
			current = session.query(Config).filter(Config.conf_name == profile_name).all()
			
			if current:
				profile = current[0]
			else:
				raise Exception, "No profile with that name! Please create one or reset the current profile with 'make config:new' or 'make config:set_current_profile'."
			self.current = profile
			return profile

	@classmethod
	def login(self, user):
		"""This should produce a string for a database engine to connect to"""

		validate_user(user)

		login = ""
		login += {{ module }}.get_driver(user)+"://"+{{ module }}.get_user(user)+":"
		login += {{ module }}.get_password(user) + "@" + {{ module }}.get_host(user)
		return login
	
	@classmethod
	def get_password(self, user):
		"""This prompts user for credentials and then returns the input if correctly matched"""

		#does the user exist?
		validate_user(user)

		#prompts for blank password, decodes all others
		return validate_password(user)

	@classmethod
	def get_user(self, user):
		validate_user(user)
		return {{ module }}.login_info()[user]['username']

	@classmethod
	def login_info(self):
		return self.logins

